
#pragma once
#include "Common/Definitions.h"

#include "Common/Math.h"
#include "Parameter.h"
#include "ParameterSet.h"

using namespace System::Collections::Generic;

namespace ttg_internal
{
	namespace utils
	{
		///<summary>
		/// Manager, that keeps all parameters.
		///</summary>
		private ref class ParameterManager sealed
		{
			private:
				static ParameterManager ^ref = nullptr;
			public:
				///<summary>
				/// Inits manager. Should be called before using of "getRef()".
				///</summary>
				static void init()
				{ ref = gcnew ParameterManager(); }
				///<summary>
				/// Closes manager. Should be called after last using of "getRef()".
				///</summary>
				static void close()
				{
					delete ref;
					ref = nullptr;
				}
				///<summary>
				/// Returns reference to instance of ParameterManager.
				///</summary>
				static ParameterManager ^getRef()
				{ return ref; }
			private:
				ParameterSet ^_root;
				Dictionary<ttg::math::uint64, Parameter ^> ^_parameters;
				ttg::math::uint64 _currentParameterID;
				Dictionary<ttg::math::uint64, ParameterSet ^> ^_sets;
				ttg::math::uint64 _currentSetID;
			private:
				///<summary>
				/// Creates empty manager.
				///</summary>
				ParameterManager();
				///<summary>
				/// Removes set and all its child sub-sets and parameters.
				///</summary>
				void removeSet(ParameterSet ^set);
			internal:
				///<summary>
				/// Locks current parameter tree to avoid its modification.
				/// Note: values of parameters will be changing.
				///</summary>
				void lock()
				{ System::Threading::Monitor::Enter(this); }
				///<summary>
				/// UnLocks current parameter tree.
				///</summary>
				void unLock()
				{ System::Threading::Monitor::Exit(this); }
				///<summary>
				/// Returns root set.
				///</summary>
				property ParameterSet ^Root
				{
					ParameterSet ^get()
					{ return _root; }
				}
				///<summary>
				/// Creates new set with required name in root set.
				/// Returns ID of created set.
				///</summary>
				ttg::math::uint64 createSet(System::String ^name)
				{ return createSet(name, 0); }
				///<summary>
				/// Creates new set with required name in requred set.
				/// Returns ID of created set.
				///</summary>
				ttg::math::uint64 createSet(System::String ^name, ttg::math::uint64 root_set);
				///<summary>
				/// Returns instance of sub-set with given ID.
				///</summary>
				ParameterSet ^findSet(ttg::math::uint64 ID);
				///<summary>
				/// Releases required parameter set.
				///</summary>
				void releaseSet(ttg::math::uint64 ID);
				///<summary>
				/// Creates parameter with required name in root set.
				/// Returns ID of created parameter.
				///</summary>
				ttg::math::uint64 createParameter(System::String ^name, System::String ^type)
				{ return createParameter(name, type, 0); }
				///<summary>
				/// Creates parameter with required name in requred set.
				/// Returns ID of created parameter.
				///</summary>
				ttg::math::uint64 createParameter(System::String ^name,
												  System::String ^type,
												  ttg::math::uint64 root_set);
				///<summary>
				/// Finds and returns instance of parameter with given ID.
				///</summary>
				Parameter ^findParameter(ttg::math::uint64 ID);
				///<summary>
				/// Releases required parameter.
				///</summary>
				void releaseParameter(ttg::math::uint64 ID);
		};
	}
}
